package com.itheima.reggie.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.common.R;
import com.itheima.reggie.entity.Category;
import com.itheima.reggie.entity.Dish;
import com.itheima.reggie.entity.DishDto;
import com.itheima.reggie.entity.DishFlavor;
import com.itheima.reggie.service.CategoryService;
import com.itheima.reggie.service.DishFlavorService;
import com.itheima.reggie.service.DishService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;


import java.util.ArrayList;

import java.util.List;
import java.util.Set;

@Slf4j
@RestController
@RequestMapping("/dish")
@Api("菜品管理")
public class DishController {

    @Autowired
    private DishService dishService;
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private DishFlavorService dishFlavorService;

    @Autowired
    private RedisTemplate redisTemplate;

    //基础分页查询
    @GetMapping("/page")
    public R<Page> page(int page, int pageSize, String name) {
        //创建 分页构造器 创建page对象 传入页码和每页显示条数
        Page<Dish> pageInfo = new Page<>(page, pageSize);
        //构建 条件构造器
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //拼接查询条件
        wrapper.like(StringUtils.isNotEmpty(name), Dish::getName, name);
        //进行排序展示
        wrapper.orderByDesc(Dish::getUpdateTime);
        //执行分页查询操作
        dishService.page(pageInfo, wrapper);
        //将dish转换为dishDto
        Page<DishDto> dishDtoPage = new Page<>();
        //除了records以外的属性全都赋值给dishDtoPage
        BeanUtils.copyProperties(pageInfo, dishDtoPage, "records");
        //转换records属性
        List<DishDto> dishDto = new ArrayList<>();
        //此时dish中装满了所有基本信息
        List<Dish> dish = pageInfo.getRecords();
        //将records封装到List集合中
        for (Dish dish1 : dish) {
            DishDto dishDto1 = new DishDto();
            //将遍历出的records封装到dishDto中
            BeanUtils.copyProperties(dish1, dishDto1);
            //根据category的id查询到数据
            Category byId = categoryService.getById(dishDto1.getCategoryId());
            //查到了category表中的所有数据 把 分类名称单独填充到dishDto中
            dishDto1.setCategoryName(byId.getName());
            //写入到集合中
            dishDto.add(dishDto1);
        }
        //把封装好的records(口味信息)封装到DishDto中
        dishDtoPage.setRecords(dishDto);
        //分好页的DishDto对象封装到R中 完成返回
        return R.success(dishDtoPage);
    }

    //菜品新增
    @PostMapping
    public R<String> save(@RequestBody DishDto dishDto) {
        log.info("包含的菜品信息为:{}", dishDto);
        /*
        重写一个方法 保存菜品基本信息的同时保存 相关菜品口味信息
        数据来源dishDto
         */
        dishService.saveWithFlavor(dishDto);
        //如果有新增菜品 那么就将redis中缓存的菜品分类数据删除
        String key = "dish_" + dishDto.getCategoryId();//获取到所属分类的id
        //调用redis方法删除
        redisTemplate.delete(key);

        return R.success("添加成功");

    }

    //菜品回显
    @GetMapping("/{id}")
    public R<DishDto> upDate(@PathVariable Long id) {
        //方法重写
        DishDto dishDto = dishService.showById(id);
        //数据回显
        return R.success(dishDto);
    }

    //菜品修改
    @PutMapping
    public R<String> upDate(@RequestBody DishDto dishDto) {
        //方法重写
        dishService.upDateWithFlavor(dishDto);
        //如是修改那么就删除全部菜品分类缓存,因可能修改菜品分类导致显示出现异常
        Set keys = redisTemplate.keys("dish_*");//代表所有dish_开头的数据
        //执行redis方法进行删除
        redisTemplate.delete(keys);
        //页面响应
        return R.success("修改菜品成功");
    }

    //停售起售
    @PostMapping("/status/{sta}")   //restful参数按照restful风接收;普通参数传递风格按照普通风格接收 不影响.............
    public R<String> status(@PathVariable Integer sta, Long[] ids) {
        //遍历集合中的内容
        for (Long id : ids) {
            //新的LambdaUpdateWrapper是LambdaQueryWrapper的升级版本
            LambdaUpdateWrapper<Dish> wrapper = new LambdaUpdateWrapper<>();
            //LambdaUpdateWrapper中有set方法 set方法是更新条件 set status = #{sta}
            wrapper.set(Dish::getStatus, sta);
            //eq依旧是where条件拼接
            //selete * from dish where id = ?
            wrapper.eq(Dish::getId, id);
            //service调用更新方法
            dishService.update(wrapper);
        }
        //停售起售方法和修改一样 因可能修改多个菜品分类下的数据所以全部删除缓存
        Set keys = redisTemplate.keys("dish_*");//代表所有dish_开头的数据
        //执行redis方法进行删除
        redisTemplate.delete(keys);
        return R.success("修改成功");
    }

    @GetMapping("/list")
    public R<List<DishDto>> list(Long categoryId, Integer status) {

        String key = "dish_" + categoryId;
        //在redis中根据值获取数据
        List<DishDto> redisDishDto = (List<DishDto>) redisTemplate.opsForValue().get(key);
        //如果根据key查不是空的那么就返回值
        if (redisDishDto != null) {
            log.info("在redis中查到的数据");
            return R.success(redisDishDto);
        }

        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //根据id获取到基本信息
        wrapper.eq(Dish::getCategoryId, categoryId);
        wrapper.eq(status != null, Dish::getStatus, status);
        //将基本信息封装如集合中
        List<Dish> dishList = dishService.list(wrapper);
        //创建一个Dto集合
        List<DishDto> dishDtoList = new ArrayList<>();
        for (Dish dish : dishList) {
            //创建一个Dto对象保存基本信息和口味信息
            DishDto dishDto = new DishDto();
            //将基本信息复制如dto中
            BeanUtils.copyProperties(dish, dishDto);
            //查询口味关联信息
            LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
            //根据id查找
            wrapper1.eq(DishFlavor::getDishId, dishDto.getId());
            //获取出口味集合
            List<DishFlavor> list = dishFlavorService.list(wrapper1);
            //将口味存到对象里
            dishDto.setFlavors(list);
            //将对象存入集合中
            dishDtoList.add(dishDto);
        }
        //如果redis中没有找到菜品相关数据 那么就会执行到这里查完后存入redis中
        redisTemplate.opsForValue().set(key, dishDtoList);
        //返回Dto
        return R.success(dishDtoList);

    }

    //菜品的删除
    @DeleteMapping
    public R<String> delete(@RequestParam List<Long> ids) {
        //条件构造器
        LambdaUpdateWrapper<Dish> wrapper = new LambdaUpdateWrapper<>();
        //in(?,?,?)
        wrapper.in(Dish::getId, ids);
        //where status = ?
        wrapper.eq(Dish::getStatus, 1);
        //count 个数
        int count = dishService.count(wrapper);
        if (count > 0) {
            throw new CustomException("存在起售商品");
        }
        dishService.removeByIds(ids);
        return R.success("删除成功");
    }

}
